﻿/*
* Copyright (c) 2010-2012 Tesla Engine Group
* 
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* 
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

using System;
using Tesla.Graphics;
using Tesla.Math;

namespace Tesla.Content {
    /// <summary>
    /// Interface for a reader that deserializes an object that implements the ISavable interface from an input.
    /// </summary>
    public interface ISavableReader : IDisposable {

        /// <summary>
        /// Gets the render system that will be used to create any graphics objects.
        /// </summary>
        IRenderSystemProvider RenderSystem {
            get;
        }

        /// <summary>
        /// Gets the content manager that is used to load any external objects.
        /// </summary>
        ContentManager ContentManager {
            get;
        }

        /// <summary>
        /// Gets if the reader has been disposed or not.
        /// </summary>
        bool IsDisposed {
            get;
        }

        /// <summary>
        /// Reads a single byte from the input.
        /// </summary>
        /// <returns>Read byte</returns>
        byte ReadByte();

        /// <summary>
        /// Reads an array of bytes from the input.
        /// </summary>
        /// <returns>Array of bytes</returns>
        byte[] ReadByteArray();

        /// <summary>
        /// Reads a 2D array of bytes from the input.
        /// </summary>
        /// <returns>2D array of bytes</returns>
        byte[,] ReadByteArray2D();

        /// <summary>
        /// Reads a single sbyte from the input.
        /// </summary>
        /// <returns>Read sbyte</returns>
        sbyte ReadSByte();

        /// <summary>
        /// Reads an array of sbytes from the input.
        /// </summary>
        /// <returns>Array of sbytes</returns>
        sbyte[] ReadSByteArray();

        /// <summary>
        /// Reads a 2D array of sbytes from the input.
        /// </summary>
        /// <returns>2D array of sbytes</returns>
        sbyte[,] ReadSByteArray2D();

        /// <summary>
        /// Reads a single char from the input.
        /// </summary>
        /// <returns>Read char</returns>
        char ReadChar();

        /// <summary>
        /// Reads an array of char from the input.
        /// </summary>
        /// <returns>Array of char</returns>
        char[] ReadCharArray();

        /// <summary>
        /// Reads a 2D array of char from the input.
        /// </summary>
        /// <returns>2D array of char</returns>
        char[,] ReadCharArray2D();

        /// <summary>
        /// Reads a single unsigned 16-bit int from the input.
        /// </summary>
        /// <returns>Read UInt16</returns>
        ushort ReadUInt16();

        /// <summary>
        /// Reads an array of unsigned 16-bit ints from the input.
        /// </summary>
        /// <returns>Array of UInt16</returns>
        ushort[] ReadUInt16Array();

        /// <summary>
        /// Reads a 2D array of unsigned 16-bit ints from the input.
        /// </summary>
        /// <returns>2D array of UInt16</returns>
        ushort[,] ReadUInt16Array2D();

        /// <summary>
        /// Reads a single unsigned 32-bit int from the input.
        /// </summary>
        /// <returns>Read UInt32</returns>
        uint ReadUInt32();

        /// <summary>
        /// Reads an array of unsigned 32-bits int from the input.
        /// </summary>
        /// <returns>Array of UInt32</returns>
        uint[] ReadUInt32Array();

        /// <summary>
        /// Reads a 2D array of unsigned 32-bit ints from the input.
        /// </summary>
        /// <returns>2D array of UInt32</returns>
        uint[,] ReadUInt32Array2D();

        /// <summary>
        /// Reads a single unsigned 64-bit int from the input.
        /// </summary>
        /// <returns>Read UInt64</returns>
        ulong ReadUInt64();

        /// <summary>
        /// Reads an array of unsigned 64-bits int from the input.
        /// </summary>
        /// <returns>Array of UInt64</returns>
        ulong[] ReadUInt64Array();

        /// <summary>
        /// Reads a 2D array of unsigned 64-bit ints from the input.
        /// </summary>
        /// <returns>2D array of UInt64</returns>
        ulong[,] ReadUInt64Array2D();

        /// <summary>
        /// Reads a single 16-bit int from the input.
        /// </summary>
        /// <returns>Read Int16</returns>
        short ReadShort();

        /// <summary>
        /// Reads an array of 16-bits int from the input.
        /// </summary>
        /// <returns>Array of Int16</returns>
        short[] ReadShortArray();

        /// <summary>
        /// Reads a 2D array of 16-bit ints from the input.
        /// </summary>
        /// <returns>2D array of Int16</returns>
        short[,] ReadShortArray2D();

        /// <summary>
        /// Reads a single 32-bit int from the input.
        /// </summary>
        /// <returns>Read Int32</returns>
        int ReadInt();

        /// <summary>
        /// Reads an array of 32-bits int from the input.
        /// </summary>
        /// <returns>Array of Int32</returns>
        int[] ReadIntArray();

        /// <summary>
        /// Reads a 2D array of 32-bit ints from the input.
        /// </summary>
        /// <returns>2D array of Int32</returns>
        int[,] ReadIntArray2D();

        /// <summary>
        /// Reads a single 64-bit int from the input.
        /// </summary>
        /// <returns>Read Int64</returns>
        long ReadLong();

        /// <summary>
        /// Reads an array of 64-bits int from the input.
        /// </summary>
        /// <returns>Array of Int64</returns>
        long[] ReadLongArray();

        /// <summary>
        /// Reads a 2D array of 64-bit ints from the input.
        /// </summary>
        /// <returns>2D array of Int64</returns>
        long[,] ReadLongArray2D();

        /// <summary>
        /// Reads a single float from the input.
        /// </summary>
        /// <returns>Read float</returns>
        float ReadSingle();

        /// <summary>
        /// Reads an array of floats from the input.
        /// </summary>
        /// <returns>Array of floats</returns>
        float[] ReadSingleArray();

        /// <summary>
        /// Reads a 2D array of floats from the input.
        /// </summary>
        /// <returns>2D array of floats</returns>
        float[,] ReadSingleArray2D();

        /// <summary>
        /// Reads a single double from the input.
        /// </summary>
        /// <returns>Read double</returns>
        double ReadDouble();

        /// <summary>
        /// Reads an array of doubles from the input.
        /// </summary>
        /// <returns>Array of doubles</returns>
        double[] ReadDoubleArray();

        /// <summary>
        /// Reads a 2D array of doubles from the input.
        /// </summary>
        /// <returns>2D array of doubles</returns>
        double[,] ReadDoubleArray2D();

        /// <summary>
        /// Reads a single bool from the input.
        /// </summary>
        /// <returns>Read bool</returns>
        bool ReadBoolean();

        /// <summary>
        /// Reads an array of bools from the input.
        /// </summary>
        /// <returns>Array of bools</returns>
        bool[] ReadBooleanArray();

        /// <summary>
        /// Reads a 2D array of bools from the input.
        /// </summary>
        /// <returns>2D array of bools</returns>
        bool[,] ReadBooleanArray2D();

        /// <summary>
        /// Reads a string from the input.
        /// </summary>
        /// <returns>Read string</returns>
        String ReadString();

        /// <summary>
        /// Reads an array of strings from the input.
        /// </summary>
        /// <returns>Array of strings</returns>
        String[] ReadStringArray();

        /// <summary>
        /// Reads a 2D array of strings from the input.
        /// </summary>
        /// <returns>2D array of strings</returns>
        String[,] ReadStringArray2D();

        /// <summary>
        /// Reads a single color struct from the input.
        /// </summary>
        /// <returns>Color struct</returns>
        Color ReadColor();

        /// <summary>
        /// Reads an array of color structs from the input.
        /// </summary>
        /// <returns>Array of color structs</returns>
        Color[] ReadColorArray();

        /// <summary>
        /// Reads a 2D array of color structs from the input.
        /// </summary>
        /// <returns>2D array of color structs</returns>
        Color[,] ReadColorArray2D();

        /// <summary>
        /// Reads a single matrix struct from the input.
        /// </summary>
        /// <returns>Matrix struct</returns>
        Matrix ReadMatrix();

        /// <summary>
        /// Reads an array of matrix structs from the input.
        /// </summary>
        /// <returns>Array of matrix structs</returns>
        Matrix[] ReadMatrixArray();

        /// <summary>
        /// Reads a 2D array of matrix structs from the input.
        /// </summary>
        /// <returns>2D array of matrix structs</returns>
        Matrix[,] ReadMatrixArray2D();

        /// <summary>
        /// Reads a single quaternion struct from the input.
        /// </summary>
        /// <returns>Quaternion struct</returns>
        Quaternion ReadQuaternion();

        /// <summary>
        /// Reads an array of quaternion structs from the input.
        /// </summary>
        /// <returns>Array of quaternion structs</returns>
        Quaternion[] ReadQuaternionArray();

        /// <summary>
        /// Reads a 2D array of quaternion structs from the input.
        /// </summary>
        /// <returns>2D array of quaternion structs</returns>
        Quaternion[,] ReadQuaternionArray2D();

        /// <summary>
        /// Reads a single Vector2 struct from the input.
        /// </summary>
        /// <returns>Vector2 struct</returns>
        Vector2 ReadVector2();

        /// <summary>
        /// Reads an array of Vector2 structs from the input.
        /// </summary>
        /// <returns>Array of Vector2 structs</returns>
        Vector2[] ReadVector2Array();

        /// <summary>
        /// Reads a 2D array of Vector2 structs from the input.
        /// </summary>
        /// <returns>2D array of Vector2 structs</returns>
        Vector2[,] ReadVector2Array2D();

        /// <summary>
        /// Reads a single Vector3 struct from the input.
        /// </summary>
        /// <returns>Vector3 struct</returns>
        Vector3 ReadVector3();

        /// <summary>
        /// Reads an array of Vector3 structs from the input.
        /// </summary>
        /// <returns>Array of Vector3 structs</returns>
        Vector3[] ReadVector3Array();

        /// <summary>
        /// Reads a 2D array of Vector3 structs from the input.
        /// </summary>
        /// <returns>2D array of Vector3 structs</returns>
        Vector3[,] ReadVector3Array2D();

        /// <summary>
        /// Reads a single Vector4 struct from the input.
        /// </summary>
        /// <returns>Vector4 struct</returns>
        Vector4 ReadVector4();

        /// <summary>
        /// Reads an array of Vector4 structs from the input.
        /// </summary>
        /// <returns>Array of Vector4 structs</returns>
        Vector4[] ReadVector4Array();

        /// <summary>
        /// Reads a 2D array of Vector4 structs from the input.
        /// </summary>
        /// <returns>2D array of Vector4 structs</returns>
        Vector4[,] ReadVector4Array2D();

        /// <summary>
        /// Reads an enum value from the input.
        /// </summary>
        /// <typeparam name="T">Enum type</typeparam>
        /// <returns>Enum value</returns>
        T ReadEnum<T>() where T : struct;

        /// <summary>
        /// Reads a savable object from the input.
        /// </summary>
        /// <typeparam name="T">Type of object to read</typeparam>
        /// <returns>Object read</returns>
        T ReadSavable<T>() where T : ISavable;

        /// <summary>
        /// Reads an array of savable objects from the input.
        /// </summary>
        /// <typeparam name="T">Type of object to read</typeparam>
        /// <returns>Array of objects read</returns>
        T[] ReadSavableArray<T>() where T : ISavable;

        /// <summary>
        /// Reads a 2D array of savable objects from the input.
        /// </summary>
        /// <typeparam name="T">Type of object to read</typeparam>
        /// <returns>2D array of objects read</returns>
        T[,] ReadSavableArray2D<T>() where T : ISavable;

        /// <summary>
        /// Reads a reference to another input that is external to this input.
        /// </summary>
        /// <typeparam name="T">Type of object to read</typeparam>
        /// <returns>Object read</returns>
        T ReadExternal<T>() where T : ISavable;
    }
}
